//
//  SKYWebViewMonitor.m
//  SkyonSDK
//
//  Created by 张二帅 on 2018/6/11.
//  Copyright © 2018年 Skyon. All rights reserved.
//

#import "SKYWebViewMonitor.h"
//#import "SKYMethodSwizzler.h"
#import <objc/runtime.h>
#import <WebKit/WebKit.h>
#import "SKYInfoAcquisitionInterface.h"
#import "SKYInfoServer.h"

static NSString *const kSKYWebViewDynamicDelegate = @"kSKYWebViewDynamicDelegate";

//void sky_Method(Class originalClass, SEL originalSel, Class swizzledClass, SEL swizzledSel) {
//    Class class = originalClass;
//    SEL originalSelector = originalSel;
//    SEL swizzledSelector = swizzledSel;
//
//    Method originalMethod = class_getInstanceMethod(class, originalSelector);
//    Method swizzledMethod = class_getInstanceMethod(swizzledClass, swizzledSelector);
//
//    BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
//    if (success) {
//        class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
//    } else {
//        method_exchangeImplementations(originalMethod, swizzledMethod);
//    }
//}

static void sky_exchangeMethod(Class originalClass, SEL originalSel, Class replacedClass, SEL replacedSel){
    
    Method originalMethod = class_getInstanceMethod(originalClass, originalSel);
    Method replacedMethod = class_getInstanceMethod(replacedClass, replacedSel);
    
    IMP replacedMethodIMP = method_getImplementation(replacedMethod);
    
    BOOL didAddMethod = class_addMethod(originalClass,replacedSel,replacedMethodIMP,method_getTypeEncoding(replacedMethod));
    
    if (didAddMethod) {
        NSLog(@"class_addMethod succeed --> (%@)", NSStringFromSelector(replacedSel));
        Method newMethod = class_getInstanceMethod(originalClass, replacedSel);
        method_exchangeImplementations(originalMethod, newMethod);
    }
}

NSInteger SKYWKWebViewDidFinishCookieAfterTime = 3;
@interface SKYWebViewMonitor()<UIWebViewDelegate,WKNavigationDelegate>

@end

@implementation SKYWebViewMonitor

+ (void)exchangeUIWebViewDelegateMethod:(Class)aClass {
    sky_exchangeMethod(aClass, @selector(webViewDidFinishLoad:),[self class], @selector(sky_webViewDidFinishLoad:));
}

+ (void)exchangeWKNavigationDelegateMethod:(Class)aClass {
    sky_exchangeMethod(aClass, @selector(webView:didFinishNavigation:), [self class], @selector(sky_webView:didFinishNavigation:));
}

+ (NSString *)cookieCheck_id {
    return [self cookieWithCookieName:@"check_id"];
}

+ (NSString *)cookieLgn_ur {
    return [self cookieWithCookieName:@"sky_lgn_ur"];
}

+ (NSString *)cookieWithCookieName:(NSString *)cookieName {
    NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    __block NSString *cookieValue = @"";
    [storage.cookies enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([obj.properties[NSHTTPCookieName] isEqualToString:cookieName]) {
            cookieValue = obj.properties[NSHTTPCookieValue];
        }
    }];
    return cookieValue;
}

+ (void)sendWKWebViewInfoAcquisitionWithWebView:(WKWebView *)webView  API_AVAILABLE(ios(8.0)){
    __block NSString *check_id = @"";
    __block NSString *lgn_ur = @"";
    [webView evaluateJavaScript:@"document.cookie" completionHandler:^(NSString *_Nullable cookie, NSError * _Nullable error) {
        if (cookie != nil) {
            NSArray *cookieArray = [cookie componentsSeparatedByString:@";"];
            [cookieArray enumerateObjectsUsingBlock:^(NSString  *_Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                NSArray *cookieItem = [obj componentsSeparatedByString:@"="];
                if (cookieItem.count > 0) {
                    NSString *key = [NSString stringWithFormat:@"%@",[cookieItem firstObject]];
                    key = [key stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
                    NSString *value = [cookieItem lastObject];
                    if ([key isEqualToString:@"check_id"]) {
                        check_id = value;
                    } else if ([key isEqualToString:@"sky_lgn_ur"]) {
                        lgn_ur = value;
                    }
                }
            }];
            if ([SKYInfoServer sharedInstance].logEnabled) {
                NSLog(@"document.cookie:%@",cookie);
            }
        } else {
            if ([SKYInfoServer sharedInstance].logEnabled) {
                NSLog(@"document.cookie error:%@",error.localizedDescription);
            }
        }
        if (check_id.length <= 0) {
            check_id = [self randomCookieCheck_id];
            NSString *js = [NSString stringWithFormat:@"document.cookie = 'check_id=%@'",check_id];
            [webView evaluateJavaScript:js completionHandler:^(id _Nullable rep, NSError * _Nullable error) {
                if (error) {
                    if ([SKYInfoServer sharedInstance].logEnabled) {
                        NSLog(@"SDK插入document.cookie = 'check_id=%@'\n异常：%@",check_id,error.localizedDescription);
                    }
                } else {
                    [self sendWKWebViewInfoAcquisitionWithWebView:webView];
                }
            }];
        } else {
            [SKYInfoAcquisitionInterface sendWebViewLoadWithCookieCheck_id:check_id lgn_ur:lgn_ur title:webView.title urlString:webView.URL.absoluteString];
        }
    }];
}

+ (NSString *)randomCookieCheck_id {
    NSString *guid = @"";
    for (int i = 0; i < 16; i++) {
        int num = abs(rand())%0xF;
        guid = [NSString stringWithFormat:@"%@%x",guid,num];
    }
    return guid;
}

/**
 发送web采集采集
 */
+ (void)sendWebViewInfoAcquisitionWithTitle:(NSString *)title urlString:(NSString *)urlString {
    [SKYInfoAcquisitionInterface sendWebViewLoadWithCookieCheck_id:[SKYWebViewMonitor cookieCheck_id] lgn_ur:[SKYWebViewMonitor cookieLgn_ur] title:title urlString:urlString];
}

#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
    [SKYWebViewMonitor sendWebViewInfoAcquisitionWithTitle:title urlString:webView.request.URL.absoluteString];
}

- (void)sky_webViewDidFinishLoad:(UIWebView *)webView {
    NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
    [SKYWebViewMonitor sendWebViewInfoAcquisitionWithTitle:title urlString:webView.request.URL.absoluteString];
    [self sky_webViewDidFinishLoad:webView];
}

#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation  API_AVAILABLE(ios(8.0)){
    [SKYWebViewMonitor sendWKWebViewInfoAcquisitionWithWebView:webView];
}

- (void)sky_webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation  API_AVAILABLE(ios(8.0)){
    [SKYWebViewMonitor sendWKWebViewInfoAcquisitionWithWebView:webView];
    [self sky_webView:webView didFinishNavigation:navigation];
}

@end


@interface UIWebView (SKYWebViewMonitor)

@end

@implementation UIWebView (SKYWebViewMonitor)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        method_exchangeImplementations(class_getInstanceMethod([UIWebView class], @selector(setDelegate:)), class_getInstanceMethod([UIWebView class], @selector(sky_setDelegate:)));
        method_exchangeImplementations(class_getInstanceMethod([UIWebView class], @selector(loadRequest:)), class_getInstanceMethod([UIWebView class], @selector(sky_loadRequest:)));
    });
}

- (void)sky_setDelegate:(id <UIWebViewDelegate>)delegate {
    [self sky_setDelegate:delegate];
    if ([delegate isKindOfClass:[SKYWebViewMonitor class]]) {
        return;
    }
    Class aClass = [delegate class];
    [SKYWebViewMonitor exchangeUIWebViewDelegateMethod:aClass];
}

- (void)sky_loadRequest:(NSURLRequest *)request {
    if (self.delegate == nil) {
        SKYWebViewMonitor *webViewMonitor = [[SKYWebViewMonitor alloc] init];
        objc_setAssociatedObject(self, &kSKYWebViewDynamicDelegate, webViewMonitor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        self.delegate = webViewMonitor;
    }
    [self sky_loadRequest:request];
}


@end


@interface WKWebView (SKYWebViewMonitor)

@end

@implementation WKWebView (SKYWebViewMonitor)

+ (void)load {
    if (@available(iOS 8.0, *)) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            method_exchangeImplementations(class_getInstanceMethod([WKWebView class], @selector(setNavigationDelegate:)), class_getInstanceMethod([WKWebView class], @selector(sky_setNavigationDelegate:)));
            method_exchangeImplementations(class_getInstanceMethod([WKWebView class], @selector(loadRequest:)), class_getInstanceMethod([WKWebView class], @selector(sky_loadRequest:)));
        });
    }
}

- (void)sky_setNavigationDelegate:(id <WKNavigationDelegate>)delegate {
    [self sky_setNavigationDelegate:delegate];
    if ([delegate isKindOfClass:[SKYWebViewMonitor class]]) {
        return;
    }
    Class aClass = [delegate class];
    [SKYWebViewMonitor exchangeWKNavigationDelegateMethod:aClass];
}

- (void)sky_loadRequest:(NSURLRequest *)request {
    if (self.navigationDelegate == nil) {
        SKYWebViewMonitor *webViewMonitor = [[SKYWebViewMonitor alloc] init];
        objc_setAssociatedObject(self, &kSKYWebViewDynamicDelegate, webViewMonitor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        self.navigationDelegate = webViewMonitor;
    }
    [self sky_loadRequest:request];
}


@end











